﻿@page "/system/audittrails"
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.DTOs
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.PaginationQuery
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Specifications
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Caching
@using CleanArchitecture.Blazor.Server.UI.Components.UtcToLocalTime
@using CleanArchitecture.Blazor.Server.UI.Services.JsInterop

@attribute [Authorize(Policy = Permissions.AuditTrails.View)]
@inject IStringLocalizer<AuditTrails> L
<PageTitle>@Title</PageTitle>

<MudDataGrid ServerData="@(ServerReload)"
             T="AuditTrailDto"
             FixedHeader="true"
             FixedFooter="true"
             @bind-RowsPerPage="_defaultPageSize"
             Height="calc(100vh - 300px)"
             Loading="@_loading"
             Hover="true" @ref="_table">
    <ToolBarContent>
        <MudStack Row Spacing="0" Class="flex-grow-1" Justify="Justify.SpaceBetween">
            <MudStack Row AlignItems="AlignItems.Start">
                <MudIcon Icon="@Icons.Material.Filled.ReceiptLong" Size="Size.Large" />
                <MudStack Spacing="0">
                    <MudText Typo="Typo.subtitle2" Class="mb-2">@Title</MudText>
                    <MudEnumSelect Style="min-width:120px" TEnum="AuditTrailListView" ValueChanged="OnChangedListView" Value="Query.ListView" Dense="true" Label="@L["List View"]">
                    </MudEnumSelect>
                </MudStack>
            </MudStack>
            <MudStack Spacing="0" AlignItems="AlignItems.End">
                <MudToolBar Dense WrapContent="true" Class="py-1 px-0">
                    <MudButton OnClick="@(() => OnRefresh())"
                               StartIcon="@Icons.Material.Outlined.Refresh">
                        @ConstantString.Refresh
                    </MudButton>

                </MudToolBar>
                <MudStack Row Spacing="1" AlignItems="AlignItems.End">
                    <MudEnumSelect TEnum="AuditType?" Placeholder="@L["Search by audit type"]" Value="@Query.AuditType" Clearable="true" ValueChanged="@(s => OnSearch(s))" Style="min-width:120px" FullWidth="true"> </MudEnumSelect>
                    <MudHidden Breakpoint="Breakpoint.SmAndDown">
                        <MudTextField T="string" ValueChanged="@(s => OnSearch(s))" Value="@Query.Keyword" Placeholder="Search" Adornment="Adornment.End" Style="min-width:120px" FullWidth="true"
                                      AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Small">
                        </MudTextField>
                    </MudHidden>
                </MudStack>
            </MudStack>
        </MudStack>


    </ToolBarContent>
    <Columns>
        <HierarchyColumn T="AuditTrailDto" ButtonDisabledFunc="@(x => x.AuditType == AuditType.None)" />
        <PropertyColumn Property="x => x.UserId" Title="@L[_currentDto.GetMemberDescription(x => x.UserId)]">
            <CellTemplate>
                <div class="d-flex flex-column">
                    <MudText Typo="Typo.body2">@context.Item.Owner?.UserName</MudText>
                    <MudText Typo="Typo.body2" Class="mud-text-secondary">@context.Item.UserId</MudText>
                </div>
            </CellTemplate>
        </PropertyColumn>
        <PropertyColumn Property="x => x.AuditType" Title="@L[_currentDto.GetMemberDescription(x => x.AuditType)]" />
        <PropertyColumn Property="x => x.TableName" Title="@L[_currentDto.GetMemberDescription(x => x.TableName)]" />
        <PropertyColumn Property="x => x.PrimaryKey" Title="@L[_currentDto.GetMemberDescription(x => x.PrimaryKey)]" />
        <PropertyColumn Property="x => x.DateTime" Title="@L[_currentDto.GetMemberDescription(x => x.DateTime)]">
            <CellTemplate>
                <UtcToLocal UTCDateTime="@context.Item.DateTime"></UtcToLocal>
            </CellTemplate>
        </PropertyColumn>
    </Columns>
    <ChildRowContent>
        <MudCard Elevation="0" Class="d-flex flex-grow-0">
            <MudCardHeader>
                <CardHeaderContent>
                    <MudText Typo="Typo.body1">
                        <strong>@L[context.Item.TableName!]</strong>
                    </MudText>
                </CardHeaderContent>
            </MudCardHeader>
            <MudCardContent Class="py-3">
                <MudExpansionPanels Dense Class="mt-2" Elevation="0" MultiExpansion>
                    <MudExpansionPanel Dense Gutters>
                        <TitleContent>
                            <MudStack Row AlignItems="AlignItems.Center" Spacing="2">
                                @if (context.Item.IsSuccessful)
                                {
                                    <MudIcon Size="Size.Small" Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" ></MudIcon>
                                }
                                else
                                {
                                    <MudIcon Size="Size.Small" Icon="@Icons.Material.Filled.ErrorOutline" Color="Color.Error" ></MudIcon>
                                }
                                <MudText>@L["History data"]</MudText>
                            </MudStack>
                        </TitleContent>
                        <ChildContent>
                            <MudSimpleTable Hover="true" Dense Elevation="0" Bordered="false">
                                <thead>
                                    <tr>
                                        <th>@L["Field Name"]</th>
                                        <th>@L[_currentDto.GetMemberDescription(x => x.OldValues)]</th>
                                        <th>@L[_currentDto.GetMemberDescription(x => x.NewValues)]</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    @foreach (var field in context.Item.NewValues?.Any() ?? false ? context.Item.NewValues : context.Item.OldValues?.Any() ?? false ? context.Item.OldValues : new Dictionary<string, object?>())
                                    {
                                        <tr>
                                            <td>@field.Key</td>
                                            <td class="mud-text-secondary">@(context.Item.OldValues?.ContainsKey(field.Key) ?? false ? context.Item.OldValues[field.Key] : string.Empty)</td>
                                            <td>@(context.Item.NewValues?.ContainsKey(field.Key) ?? false ? context.Item.NewValues[field.Key] : string.Empty)</td>
                                        </tr>
                                    }
                                </tbody>
                            </MudSimpleTable>
                        </ChildContent>
                    </MudExpansionPanel>
                    @if (@context.Item.IsSuccessful == false)
                    {
                        <MudExpansionPanel Text="@L[_currentDto.GetMemberDescription(x=>x.ErrorMessage)]" Dense Gutters>
                            <MudText Typo="Typo.body2">@context.Item.ErrorMessage</MudText>
                        </MudExpansionPanel>
                    }
                    <MudExpansionPanel Text="@L[_currentDto.GetMemberDescription(x=>x.DebugView)]" Dense Gutters>
                        <MudText Typo="Typo.body2">@context.Item.DebugView</MudText>
                    </MudExpansionPanel>
                </MudExpansionPanels>
            </MudCardContent>
        </MudCard>
    </ChildRowContent>
    <NoRecordsContent>
        <MudText>@ConstantString.NoRecords</MudText>
    </NoRecordsContent>
    <LoadingContent>
        <MudText>@ConstantString.Loading</MudText>
    </LoadingContent>
    <PagerContent>
        <MudDataGridPager PageSizeOptions="@(new[] { 10, 15, 30, 50, 100, 500, 1000 })" />
    </PagerContent>
</MudDataGrid>

@code
{
    public string Title { get; private set; } = "Audit Trails";
    private MudDataGrid<AuditTrailDto> _table = null!;
    private bool _loading;
    private int _defaultPageSize = 15;
    private readonly AuditTrailDto _currentDto = new();
    private AuditTrailsWithPaginationQuery Query { get; } = new();
    [CascadingParameter] private UserProfile? UserProfile { get; set; }
    protected override Task OnInitializedAsync()
    {
        Title = L[_currentDto.GetClassDescription()];
        return Task.CompletedTask;
    }

    private async Task<GridData<AuditTrailDto>> ServerReload(GridState<AuditTrailDto> state)
    {
        try
        {
            _loading = true;
            Query.CurrentUser = UserProfile;
            Query.OrderBy = state.SortDefinitions.FirstOrDefault()?.SortBy ?? "Id";
            Query.SortDirection = state.SortDefinitions.FirstOrDefault()?.Descending ?? true ? SortDirection.Descending.ToString() : SortDirection.Ascending.ToString();
            Query.PageNumber = state.Page + 1;
            Query.PageSize = state.PageSize;

            var result = await Mediator.Send(Query).ConfigureAwait(false);
            return new GridData<AuditTrailDto> { TotalItems = result.TotalItems, Items = result.Items };
        }
        finally
        {
            _loading = false;
        }
    }

    private async Task OnChangedListView(AuditTrailListView listview)
    {
        Query.ListView = listview;
        await _table.ReloadServerData();
    }

    private async Task OnSearch(string text)
    {
        Query.Keyword = text;
        await _table.ReloadServerData();
    }

    private async Task OnSearch(AuditType? val)
    {
        Query.AuditType = val;
        await _table.ReloadServerData();
    }

    private async Task OnRefresh()
    {
        AuditTrailsCacheKey.Refresh();
        Query.Keyword = string.Empty;
        await _table.ReloadServerData();
    }

    private Task OnShowDetail(AuditTrailDto dto)
    {
        dto.ShowDetails = !dto.ShowDetails;
        return Task.CompletedTask;
    }
}